/*
 * logger.h
 *
 *  Created on: Apr 7, 2013
 *      Author: nick
 */

#ifndef LOGGER_H_
#define LOGGER_H_

#include <cstring>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>

#include "../hpp/exceptions.hpp"


namespace Logging {
	enum Level {
		TRACE, DEBUG, INFO, WARN, ERROR, FATAL
	};

	std::ostream & operator<<(std::ostream & out, const Level level);

	class LogMessage {
	private:
		const std::string text;
		char* creationTime;
		const Level severityLevel;
	public:
		LogMessage(const std::string & text, const Level severityLevel);
		Level getSeverityLevel() const;
		const std::string & getText() const;
		const char* getCreationTime() const;
		friend std::ostream & operator<<(std::ostream & out, const LogMessage & message);
	};

	class Destination {
	public:
		virtual void send(const LogMessage & message) = 0;
		virtual ~Destination() {}
	};

	class Logger {
	private:
		Destination * destination;
		Level severityLevel;

		Logger();
		Logger(const Logger & logger);
		Logger & operator=(const Logger & logger);
	public:
		static Logger & getInstance();
		void setDestination(Destination * destination);
		void setSeverityLevel(const Level level);
		void log(const LogMessage & message);
		~Logger();
	};


	class LocalDestination : public Destination {
	private:
		std::ostream * output;
		const bool isFile;
	public:
		LocalDestination(std::ostream & output = std::clog);
		LocalDestination(const char* fileName);
		void send(const Logging::LogMessage & message);
		~LocalDestination();
	};

	class RemoteDestination : public Destination {
	public:
		RemoteDestination();
	};

	void trace(const std::string & text);
	void debug(const std::string & text);
	void info(const std::string & text);
	void warn(const std::string & text);
	void error(const std::string & text);
	void fatal(const std::string & text);
}


#endif /* LOGGER_H_ */
